#ifndef PROTOCOLPARSER_H
#define PROTOCOLPARSER_H

#include <QObject>
#include <QByteArray>

/*
 * 协议说明
 *
 * 该协议用于数据的封装和解析，其数据格式如下：
 *
 * 数据包格式:
 *
 * [帧头1] [帧头2] [功能码] [长度低字节] [长度高字节] [负载数据] [CRC16校验]
 *
 * 字段说明:
 *
 * - 帧头（2字节）:
 *   - 帧头1: 固定为 0xAA
 *   - 帧头2: 固定为 0x55
 *   - 用于标识数据包的开始，并帮助接收端同步数据包。
 *
 * - 功能码（1字节）:
 *   - 表示数据包的功能或命令类型，例如读数据、写数据等。
 *   - 功能码决定了数据包的具体操作或响应内容。
 *
 * - 长度字段（2字节）:
 *   - 长度低字节: 负载数据的长度的低字节（第一个字节）。
 *   - 长度高字节: 负载数据的长度的高字节（第二个字节）。
 *   - 这两个字节合并在一起表示负载数据的总长度，确保接收端能够正确读取负载数据。
 *
 * - 负载数据（可变长度）:
 *   - 实际需要传输的数据。
 *   - 负载数据的长度由前面的长度字段指定。
 *
 * - CRC16校验（2字节）:
 *   - CRC16（循环冗余校验）用于校验数据包的完整性。
 *   - 计算方式是对从帧头到负载数据的所有字节进行 CRC16 运算，以检测数据在传输过程中是否发生错误。
 *   - CRC16 校验码包括两个字节，低字节在前，高字节在后。
 *
 * 示例:
 *
 * 假设功能码为 0x01，负载数据为 0x123456，则数据包构造如下：
 *
 * 1. 帧头: 0xAA 0x55
 * 2. 功能码: 0x01
 * 3. 长度字段: 负载数据长度 0x06（6 字节），即 0x06 0x00（低字节在前）
 * 4. 负载数据: 0x12 0x34 0x56
 * 5. CRC16 校验: 计算所有前面字节的 CRC16 值，附加在数据包的末尾
 *
 * 数据包最终可能如下（假设 CRC16 计算结果为 0xABCD）:
 *
 * 0xAA 0x55 0x01 0x06 0x00 0x12 0x34 0x56 0xCD 0xAB
 *
 * 解析过程:
 *
 * 在接收端：
 * 1. 检查帧头是否匹配。
 * 2. 读取功能码和长度字段。
 * 3. 读取负载数据，并根据长度字段确定其长度。
 * 4. 计算 CRC16 校验码，并与数据包中的 CRC16 校验码进行比较，验证数据的完整性。
 *
 * 以上协议结构可以用于各种需要数据完整性校验和功能码区分的通信场景。通过确保数据包格式和校验一致性，可以提高通信的可靠性。
 */


class ProtocolParser : public QObject {
    Q_OBJECT

public:
    explicit ProtocolParser(QObject *parent = nullptr);

    // 封包函数
    QByteArray createPacket(uint8_t functionCode, const QByteArray &payload);

    // 解析整个 UDP 数据包
    bool parsePacket(const QByteArray &data, uint8_t &functionCode, int &payloadOffset);

private:
    // CRC16计算函数
    uint16_t modbus_crc16(const uint8_t *data, uint16_t length);
};

#endif // PROTOCOLPARSER_H
